﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using Medora.Core;
using Medora.DataContract;
using Medora.Model.Basic;
using Medora.Model.Institutions;

namespace Medora.Data
{
    public class ProviderRepository : EFRepository<Provider>, IProviderRepository
    {
        public ProviderRepository(DbContext dbContext) : base(dbContext){}

        public virtual Provider GetById(Guid id)
        {
            var providers= DbSet.Include(x => x.Department).Include(x=>x.Position).Include(x=>x.Speciality);
            return providers.FirstOrDefault(o=>o.Id==id);
        }

        public IEnumerable<Provider> Get(Expression<Func<Provider, bool>> filter = null, Func<IQueryable<Provider>, IOrderedQueryable<Provider>> orderBy = null, string includeProperties = "")
        {
            IQueryable<Provider> query = DbSet.Include(x => x.Department).Include(x=>x.Position).Include(x=>x.Speciality);

            if (filter != null)
            {
                query = query.Where(filter);
            }

            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }

            if (orderBy != null)
            {
                return orderBy(query);
            }
            else
            {
                return query;
            }
        }

        public IEnumerable<Provider> GetLazy(Expression<Func<Provider, bool>> filter = null, Func<IQueryable<Provider>, IOrderedQueryable<Provider>> orderBy = null, string includeProperties = "")
        {
            IQueryable<Provider> query = DbSet.Include(x => x.Speciality);

            if (filter != null)
            {
                query = query.Where(filter);
            }

            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }

            if (orderBy != null)
            {
                return orderBy(query);
            }
            else
            {
                return query;
            }
        }

        public IEnumerable<Provider> GetTake(int pageSize, int page, Expression<Func<Provider, bool>> filter = null, SortInfo sortInfo = null, string includeProperties = "")
        {
            IQueryable<Provider> query = DbSet.Include(x => x.Department).Include(x => x.Position).Include(x => x.Speciality);

            if (filter != null)
            {
                query = query.Where(filter);
            }

            foreach (var includeProperty in includeProperties.Split
                (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
            {
                query = query.Include(includeProperty);
            }


            if (sortInfo != null)
            {
                sortInfo.Field = sortInfo.Field.FirstCharToUpper();

                var propertyType = typeof(Department).GetProperty(sortInfo.Field).PropertyType.ToString();
                switch (propertyType)
                {
                    case "System.DateTime":
                        var dateExpr = _sortConstructor.GetSortExpessionByDateTime(sortInfo.Field);
                        return sortInfo.Direction == SortOrderType.Asc
                                   ? query.OrderBy(dateExpr).Skip((page - 1) * pageSize).Take(pageSize)
                                   : query.OrderByDescending(dateExpr).Skip((page - 1) * pageSize).Take(pageSize);
                    case "System.Int16":
                    case "System.Int32":
                    case "System.Int64":
                        var intExpr = _sortConstructor.GetSortExpessionByInt(sortInfo.Field);
                        return sortInfo.Direction == SortOrderType.Asc
                                   ? query.OrderBy(intExpr).Skip((page - 1) * pageSize).Take(pageSize)
                                   : query.OrderByDescending(intExpr).Skip((page - 1) * pageSize).Take(pageSize);
                    case "System.Double":
                    case "System.Decimal":
                        var doubleExpr = _sortConstructor.GetSortExpessionByDouble(sortInfo.Field);
                        return sortInfo.Direction == SortOrderType.Asc
                                   ? query.OrderBy(doubleExpr).Skip((page - 1) * pageSize).Take(pageSize)
                                   : query.OrderByDescending(doubleExpr).Skip((page - 1) * pageSize).Take(pageSize);
                    default:
                        var stringExpr = _sortConstructor.GetSortExpessionByString(sortInfo.Field);
                        return sortInfo.Direction == SortOrderType.Asc
                                   ? query.OrderBy(stringExpr).Skip((page - 1) * pageSize).Take(pageSize)
                                   : query.OrderByDescending(stringExpr).Skip((page - 1) * pageSize).Take(pageSize);
                }

            }
            return query.Take(pageSize);
        }
    }
}